﻿namespace Sofire.Data
{
    using System;
    using System.Data.Common;

    /// <summary>
    /// 表示一个可更新的查询结果。
    /// </summary>
    public interface ICanUpdateQueryResult : IQueryResult
    {
        #region Methods

        /// <summary>
        /// 提交当前返回值，更新数据库对应的记录。
        /// <para>如果在更新过程中发生了异常，将会通知当前查询结果的 Exception 属性。</para>
        /// </summary>  
        /// <param name="continueUpdateOnError">指示在行更新过程中遇到错误时是否生成异常。如果要继续更新而不生成异常，则为 true，否则为 false。</param>
        /// <returns>返回更新的行数。如果返回一个 0 则表示当前返回值并改动，如果返回一个小于 0 的整数，则表示更新发生了异常。</returns>
        int Update(bool continueUpdateOnError);

        #endregion Methods
    }

    /// <summary>
    /// 表示一个可更新的查询结果。
    /// </summary>
    /// <typeparam name="TValue">返回值的类型。</typeparam>
    public abstract class CanUpdateQueryResultBase<TValue> : QueryResultBase<TValue>, ICanUpdateQueryResult
    {
        #region Constructors

        /// <summary>
        /// 初始化 <see cref="Sofire.Data.CanUpdateQueryResultBase&lt;TValue&gt;"/> 的新实例。
        /// </summary>
        internal CanUpdateQueryResultBase()
        {
            this._destructor = false;
        }

        #endregion Constructors

        /// <summary>
        /// 获取一个值，表示值是否已被修改。
        /// </summary>
        public abstract bool IsChanged { get; }
        #region Methods

        /// <summary>
        /// 提交当前返回值，更新数据库对应的记录。
        /// <para>如果在更新过程中发生了异常，将会通知当前查询结果的 Exception 属性。</para>
        /// </summary>  
        /// <returns>返回更新的行数。如果返回一个 0 则表示当前返回值并改动，如果返回一个小于 0 的整数，则表示更新发生了异常。</returns>
        public int Update()
        {
            return this.Update(false);
        }

        /// <summary>
        /// 提交当前返回值，更新数据库对应的记录。
        /// <para>如果在更新过程中发生了异常，将会通知当前查询结果的 Exception 属性。</para>
        /// </summary>  
        /// <param name="continueUpdateOnError">指示在行更新过程中遇到错误时是否生成异常。如果要继续更新而不生成异常，则为 true，否则为 false。</param>
        /// <returns>返回更新的行数。如果返回一个 0 则表示当前返回值并改动，如果返回一个小于 0 的整数，则表示更新发生了异常。</returns>
        public int Update(bool continueUpdateOnError)
        {
            this.ToSuccessed();
            try
            {
                var dataAdapter = this._QueryEngine.CreateDataAdapter(this._Command);
                dataAdapter.ContinueUpdateOnError = continueUpdateOnError;
                this._QueryEngine.CreateCommandBuilder().DataAdapter = dataAdapter;
                using(dataAdapter)
                {
                    return this.UpdateValue(dataAdapter);
                }
            }
            catch(System.Data.DBConcurrencyException)
            {
                this.ToFailded("更新失败，当前数据已被其他用户修改！");
            }
            catch(Exception ex)
            {
                this.ToFailded(ex);
            }
            return -1;
        }

        /// <summary>
        /// 更新结果的返回值。
        /// </summary>
        /// <param name="dataAdapter">查询结果对应的数据适配器。</param>
        /// <returns>返回更新的行数。如果返回一个 0 则表示当前返回值并改动，如果返回一个小于 0 的整数，则表示更新发生了异常。</returns>
        protected abstract int UpdateValue(DbDataAdapter dataAdapter);

        #endregion Methods
    }
}